/**
  ******************************************************************************
  * @file         lock_task.c
  * @brief        应用层锁体任务功能逻辑
  * @author       Leo
  * @date         2019-1-5
  * @version      v001
  * @copyright    dxtc
  * 
  * @note         凯迪仕·智能锁
  *
  ******************************************************************************
  */
#include "device.h"
#include "component.h"
#include "motor524.h"
/* 调试打印接口 */
#define LOCK524_LOG(format, ...)			OSAL_LOG("[lock524.c] " C_GREEN format C_NONE, ##__VA_ARGS__)






/* 事件 */
#define EVENT_MOTOR_STOP         (0X00000001)  //电机停止事件
#define EVENT_AUTO_LOCKED        (0X00000002)  //自动上锁事件




/* 电机控制参数 */
#define MOTOR_TURN_TIME         (600)   //电机运行时间600ms
#define MOTOR_AUTO_LOCKED_TIME  (5000)  //自动上锁时间 5s

/* 环形缓存长度、大小定义 */
#define LOCK_RING_BUFFER_LEN				(5)

/* 锁体状态 */
__NVRAM static enum
{
	LOCK_STA_UNKNOW,    //未知状态
	LOCK_STA_LOCKING,   //正在上锁
	LOCK_STA_UNLOCKING, //正在开锁
	LOCK_STA_LOCKED,    //已上锁
	LOCK_STA_UNLOCK,    //已开锁
}lockStatus = LOCK_STA_UNKNOW;

typedef struct 
{
    UserAction_enum_t action;   		//动作
    char *name;                 		//传感器名称
}LockSensorAction_t;

__EFRAM static uint8_t M_KEY_status;
static RingBufferHandle_t rbHandle = NULL;

/* 锁体上报消息标志 */
// static FlagStatus lockReportMsgFlag = RESET;

/**
  * @brief  电机停止
  *         
  * @note   
  */
static void LockTask_MotorStop(void)
{
	Motor524_Stop();
	LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
	if (lockStatus == LOCK_STA_LOCKING)
	{
		lockStatus = LOCK_STA_LOCKED;
		lockMsg.lock = LOCK_ACTION_LOCKED;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
	}
	else if (lockStatus == LOCK_STA_UNLOCKING)
	{
		lockStatus = LOCK_STA_UNLOCK;
		lockMsg.lock = LOCK_ACTION_UNLOCK_BACK;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
		OSAL_EventDelete(COMP_LOCK, EVENT_AUTO_LOCKED);
		OSAL_EventSingleCreate(COMP_LOCK, EVENT_AUTO_LOCKED, MOTOR_AUTO_LOCKED_TIME, EVT_PRIORITY_MEDIUM);
	}
}

/**
  * @brief  上锁接口函数
  *         
  * @note   
  */
static ErrorStatus LockTask_Locked(void)
{
	LockMsg_t lockMsg;
    memset(&lockMsg, 0, sizeof(lockMsg));
	if (lockStatus == LOCK_STA_LOCKING || lockStatus == LOCK_STA_UNLOCKING)
	{
		lockMsg.lock = LOCK_ACTION_BUSY;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
		return ERROR;
	}
	else if (lockStatus == LOCK_STA_LOCKED)
	{
		lockMsg.lock = LOCK_ACTION_LOCKED;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
		return ERROR;
	}
	LOCK524_LOG("LockTask_Locked\r\n");
	Motor524_TurnLeft();
	lockStatus = LOCK_STA_LOCKING;
	OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_STOP);
	return OSAL_EventSingleCreate(COMP_LOCK, EVENT_MOTOR_STOP, MOTOR_TURN_TIME, EVT_PRIORITY_HIGH);
}

/**
  * @brief  产测上锁接口函数
  *         
  * @note   
  */
static ErrorStatus LockTask_Locked_test(void)
{
	LOCK524_LOG("LockTask_Locked_test\r\n");
	Motor524_TurnLeft();
}

/**
  * @brief  产测停止接口函数
  *         
  * @note   
  */
static ErrorStatus LockTask_Stop_test(void)
{
	LOCK524_LOG("LockTask_Stop_test\r\n");
	Motor524_Stop();
}

/**
  * @brief  产测开锁接口函数
  *         
  * @note   
  */
static ErrorStatus LockTask_Unlock_test(void)
{
	LOCK524_LOG("LockTask_Unlock_test\r\n");
	Motor524_TurnRight();
}
/**
  * @brief  开锁接口函数
  *         
  * @note   
  */
static ErrorStatus LockTask_Unlock(void)
{
	LockMsg_t lockMsg;
	memset(&lockMsg, 0, sizeof(lockMsg));
	if (lockStatus == LOCK_STA_LOCKING || lockStatus == LOCK_STA_UNLOCKING)
	{
		lockMsg.lock = LOCK_ACTION_BUSY;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
		return ERROR;
	}
	else if (lockStatus == LOCK_STA_UNLOCK)
	{
		lockMsg.lock = LOCK_ACTION_UNLOCK_BACK;
		OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
		OSAL_EventDelete(COMP_LOCK, EVENT_AUTO_LOCKED);
		OSAL_EventSingleCreate(COMP_LOCK, EVENT_AUTO_LOCKED, MOTOR_AUTO_LOCKED_TIME, EVT_PRIORITY_MEDIUM);
		return ERROR;
	}
	LOCK524_LOG("LockTask_Unlock\r\n");
	Motor524_TurnRight();
	lockStatus = LOCK_STA_UNLOCKING;
	OSAL_EventDelete(COMP_LOCK, EVENT_MOTOR_STOP);
	return OSAL_EventSingleCreate(COMP_LOCK, EVENT_MOTOR_STOP, MOTOR_TURN_TIME, EVT_PRIORITY_HIGH);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/* Lock组件API函数类型 */
static ErrorStatus Lock_Ctrl_Sub(LockCtrl_enum_t ctrl)
{
    switch((uint8_t)ctrl)
    {
        case LOCK_CTRL_LOCKED:
			LockTask_Locked();
            break;
        case LOCK_CTRL_UNLOCK:
			LockTask_Unlock();
            break;
        default:
            break;
    }
    return SUCCESS;
}


/* Lock组件API函数类型 */
static ErrorStatus Lock_TestCtrl_Sub(LockCtrl_enum_t ctrl)
{
    switch((uint8_t)ctrl)
    {
        case LOCK_CTRL_LOCKED:
			LockTask_Locked_test();

            break;
        case LOCK_CTRL_UNLOCK:
			LockTask_Unlock_test();
            break; 
		case LOCK_CTRL_STOP:
			LockTask_Stop_test();
            break;
        default:
            break;
    }
    return SUCCESS;
}

static void Lock524_ProcessMbox(uint8_t *msg)
{
    switch (msg[0])
    {
		case LOCK_MBOX_CTRL:
		{
			uint8_t ctrl;
			ctrl = msg[1];
			Lock_Ctrl_Sub((LockCtrl_enum_t)ctrl);
		}
			break;

		case LOCK_MBOX_TESTCTRL:
		{
			uint8_t test_ctrl;
			test_ctrl = msg[3];
			LOCK524_LOG("test_ctrl:%d\n",test_ctrl);
			Lock_TestCtrl_Sub((LockCtrl_enum_t)test_ctrl);
		}
			break;
		default:
			
			break;
    }
}

static void Lock524_ProcessISR(void)
{
   	LockSensorAction_t sensor;

	while (OSAL_RingBufferRead(rbHandle, &sensor) == SUCCESS)
	{
		if (strcmp(sensor.name, "M-KEY") == 0)
		{
			LOCK524_LOG("\r\n\r\nsensor.action:%d\r\n\r\n",sensor.action);
			if(sensor.action == USER_ACTION_PRESS)
			{
				LockMsg_t lockMsg;
				lockMsg.lock = LOCK_ACTION_UNLOCK_MACH; 
				OSAL_MessagePublish(&lockMsg, sizeof(lockMsg));
			}
		}
	}
}
/**
  * @brief  锁体传感器中断 回调
  *         
  * @note   该函数以回调形式，在底层的中断函数里面调用
  */
static void Lock524_SensorStatusChange(char *name, uint8_t status, uint8_t times)
{
	LockSensorAction_t sensor;

	/* 锁体传感器动作暂存缓存区 */
	sensor.name = name;
	sensor.action = (UserAction_enum_t)status;
	OSAL_RingBufferWrite(rbHandle, &sensor);

    /* 产生ISR事件 */
    OSAL_EventCreateFromISR(COMP_LOCK);
    // printf("\r\nlock-action:%d,name:%s,times:%d\r\n",status,name,times);
}

/**
  * @brief  锁体启动
  *         
  * @note   
  */
static void Lock524_Start(void)
{
	if (rbHandle == NULL)
    {
		/* 创建环形缓存（暂存传感器状态） */
        rbHandle = OSAL_RingBufferCreate(LOCK_RING_BUFFER_LEN, sizeof(LockSensorAction_t));
		/* 注册锁体传感器端口 */
		InputPort_stu_t sensor_list[] = {
			{"M-KEY",		vPIN_B14, 	INPUT_PORT_LOGIC_HIGH, 	INPUT_PORT_FUNC_SPECIAL},//机械钥匙
		};
		InputPort_Registered(sensor_list, OSAL_LENGTH(sensor_list), Lock524_SensorStatusChange);
	}
    InputPort_EnableProt("M-KEY");
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
  * @brief  锁体任务函数
  *
  * @note   1.任务函数内不能写阻塞代码
  *         2.任务函数每次运行只处理一个事件
  *         3.任务函数必须添加到osal_config.h文件里面
  *         
  * @param  event：当前任务的所有事件
  *
  * @return 返回未处理的事件
  */
static uint32_t Lock_Task(uint32_t event)
{
	/* 系统启动事件 */
	if (event & EVENT_SYS_START)
	{
		LOCK524_LOG("Lock task start\r\n");
		Device_Enable(vPWM_1);
		Device_Enable(vPWM_2);
		Device_Write(vPIN_C2,NULL,0,1);
		#ifdef M_KEY
		Lock524_Start();
		#endif
        // OSAL_EventSingleCreate(COMP_LOCK, EVENT_AUTO_LOCKED, 100, EVT_PRIORITY_MEDIUM);//系统重新上电先先执行一次关锁
		return ( event ^ EVENT_SYS_START );
	}
    
	if (event & EVENT_SYS_MBOX)
    {
        uint8_t buffer[30] = {0};
        while (OSAL_MboxAccept(buffer))
        {
            Lock524_ProcessMbox(buffer);
        }
        return ( event ^ EVENT_SYS_MBOX );
    }
    /* 系统休眠事件 */
	if (event & EVENT_SYS_SLEEP)
	{
		OSAL_EventDelete(COMP_LOCK,EVENT_AUTO_LOCKED);
		#ifdef M_KEY
		InputPort_DisableProt("M-KEY");
		#endif
		Device_Disable(vPWM_1);
		Device_Disable(vPWM_2);
		Device_Write(vPIN_C2,NULL,0,0);
		M_KEY_status = Device_Read(vPIN_B14,NULL,0,0);
		return ( event ^ EVENT_SYS_SLEEP );
	}

	/* 锁体中断事件 */
	if (event & EVENT_SYS_ISR)
	{
        Lock524_ProcessISR();
		return ( event ^ EVENT_SYS_ISR );
	}

	/* 电机停止事件 */
	if (event & EVENT_MOTOR_STOP)
	{
		LockTask_MotorStop();
		return ( event ^ EVENT_MOTOR_STOP );
	}

	/* 自动上锁事件 */
	if (event & EVENT_AUTO_LOCKED)
	{
		if (lockStatus == LOCK_STA_UNLOCK || lockStatus == LOCK_STA_UNKNOW)
		{
			LockTask_Locked();
		}
		return ( event ^ EVENT_AUTO_LOCKED );
	}
	return 0;
}

COMPONENT_TASK_EXPORT(COMP_LOCK, Lock_Task, 0);

/**
 * @brief  Lcok定时唤醒回调
 *
 * @param  mode：模式
 * @return 
 */
static int32_t Lock_TimedWakeupHandle(uint32_t dev)
{
	if(M_KEY_status == Device_Read(vPIN_B14,NULL,0,0))
	{
		return -1;
	}
	else
	{
		return 1;
	}
}
#ifdef M_KEY
COMPONENT_WAKEUP_EXPORT(COMP_LOCK, Lock_TimedWakeupHandle, vTIMER_1); 
#endif